/** 
 * File-Name:ExceptionStackTraceRepository.java
 *
 * Created on 2011-10-2 下午02:55:29
 * 
 * @author: Neo (neolimeng@gmail.com)
 * Software Engineering Institute, Peking University, China
 * 
 * Copyright (c) 2009, Peking University
 * 
 *
 */
package com.debugassistant.dao;

import java.sql.Connection;
import java.util.List;

import neoutil.CommonRepository;
import neoutil.DaoSupport;
import neoutil.Page;

import org.apache.log4j.Logger;

import com.debugassistant.dao.dao.ESTDao;
import com.debugassistant.dao.dao.StackInfoDao;
import com.debugassistant.entity.APIInfo;
import com.debugassistant.entity.EST;
import com.debugassistant.entity.StackInfo;
import com.debugassistant.service.exception.DuplicateStackInfoException;

/**
 * Description:
 * 
 * @author: Neo (neolimeng@gmail.com) Software Engineering Institute, Peking
 *          University, China
 * @version 1.0 2011-10-2 下午02:55:29
 */
public class ESTRepository extends CommonRepository {
	private static Logger log = Logger.getLogger(ESTRepository.class);
	private static String SAVE_EST = "INSERT INTO est (uuid, fullName, tip, url, stackTraceString, entityStatus, entityDatetime, reserve01, reserve02, reserve03, reserve04, reserve05) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
	private static String SAVE_STACK_INFO = "INSERT INTO stackinfo (uuid, position, methodName, fileName, lineNum, estUuid, apiUuid, entityStatus, entityDatetime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
	private static String SQL_IS_EXIT = "SELECT * WHERE stackTraceString=? AND url=?";

	public static EST saveDistinct(EST est) {
		Connection connection = null;
		try {
			connection = DaoSupport.getConnection();
			ESTDao estDao = new ESTDao(connection);
			List<EST> ests = estDao.find(SQL_IS_EXIT, new Object[] {
					est.getStackTraceString(), est.getUrl() });
			if (ests == null || ests.size() == 0) {
				return save(est);
			} else {
				log.info("该异常信息已经存在！" + ests.size() + "个。");
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			closeConnection(connection);
		}
	}

	public static EST save(EST est) {
		Connection connection = null;
		try {
			connection = DaoSupport.getConnection();
			ESTDao estDao = new ESTDao(connection);
			StackInfoDao stackInfoDao = new StackInfoDao(connection);
			// First, save EST.
			Object[] exceptionInfoParams = { est.getUuid(), est.getFullName(),
					est.getTip(), est.getUrl(), est.getStackTraceString(),
					est.getEntityStatus(), est.getEntityDatetime(),
					est.getReserve01(), est.getReserve02(), est.getReserve03(),
					est.getReserve04(), est.getReserve05() };
			estDao.execute(SAVE_EST, exceptionInfoParams);

			// Second, save the exception StackInfos.
			List<StackInfo> stackTrace = est.getStackTrace();
			if (stackTrace == null || stackTrace.size() == 0) {
				log.info("No stack trace info!");
			} else {
				for (int i = 0; i < stackTrace.size(); i++) {
					StackInfo stackInfo = stackTrace.get(i);

					// 1. Save API info.
					APIInfo apiInfo = APIRepository
							.save(stackInfo.getApiInfo());

					if (null != apiInfo) {
						// 2. Save stack info.
						Object[] stackInfoParams = { stackInfo.getUuid(),
								stackInfo.getPosition(),
								stackInfo.getMethodName(),
								stackInfo.getFileName(),
								stackInfo.getLineNum(), est.getUuid(),
								apiInfo.getUuid(), stackInfo.getEntityStatus(),
								stackInfo.getEntityDatetime() };
						stackInfoDao.execute(SAVE_STACK_INFO, stackInfoParams);
					} else {
						log
								.error("Errors occur when saving apiInfo, bypass this stackInfo");
					}
				}
			}
			return est;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			closeConnection(connection);
		}
	}

	public static EST get(String uuid) {
		Connection connection = null;
		try {
			connection = DaoSupport.getConnection();
			ESTDao estDao = new ESTDao(connection);
			StackInfoDao stackInfoDao = new StackInfoDao(connection);

			// First, get ExceptionInfo.
			EST est = estDao.getByUuid(uuid);

			if (est != null) {
				// Second, get the exception stack trace info.
				List<StackInfo> stackTrace = stackInfoDao.getByProperty(
						"estUuid", "'" + est.getUuid() + "'");

				if (stackTrace != null && stackTrace.size() > 0) {
					est.setStackTrace(stackTrace);
				}
			}

			return est;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			closeConnection(connection);
		}
	}

	public static Page<EST> getAll(Page<EST> page) {
		Connection connection = null;
		try {
			connection = DaoSupport.getConnection();
			ESTDao estDao = new ESTDao(connection);
			return estDao.getAll(page);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			closeConnection(connection);
		}
	}

	public static List<EST> getDistinctAll() {
		Connection connection = null;
		try {
			connection = DaoSupport.getConnection();
			String sql = "SELECT * FROM `debugassistantdb`.`est` as est1 where not exists(select * from est where fullname=est1.fullname and id<est1.id);";
			ESTDao estDao = new ESTDao(connection);
			return estDao.find(sql);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			closeConnection(connection);
		}
	}

	private static StackInfo isExist(Connection connection, StackInfo stackInfo)
			throws DuplicateStackInfoException {
		String sql = "SELECT * FROM stackinfo WHERE fileName='"
				+ stackInfo.getFileName() + "' and lineNum="
				+ stackInfo.getLineNum() + " and apiUuid='"
				+ stackInfo.getApiUuid() + "'";
		StackInfoDao stackInfoDao = new StackInfoDao(connection);
		List<StackInfo> stackInfos = stackInfoDao.find(sql);
		if (stackInfos == null || stackInfos.size() == 0) {
			return null;
		} else if (stackInfos.size() == 1) {
			return stackInfos.get(0);
		} else {
			throw new DuplicateStackInfoException();
		}
	}

	/**
	 * Description:
	 * 
	 * @param args
	 *            void
	 */
	public static void main(String[] args) {
		// String stackTraceString =
		// "java.lang.NullPointerException333:tip	at com.rportal.web.action.PaperAction.uploadPaperFile(PaperAction.java:91)	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)	at java.lang.reflect.Method.invoke(Unknown Source)";
		// EST est = ESTConstructor.construct(stackTraceString);
		// ESTRepository.save(est);

		// EST est = ESTRepository.get("740fcced-6bf5-4200-a6af-f1264fb7c2a4");
		// if (null != est) {
		// System.out.println("ExceptionName:  " + est.getFullName() + "\t"
		// + est.getShortName() + "\t" + est.getTip());
		// List<StackInfo> stackTrace = est.getStackTrace();
		// if (stackTrace != null) {
		// for (int i = 0; i < stackTrace.size(); i++) {
		// StackInfo stackInfo = stackTrace.get(i);
		// System.out.println("@ " + stackInfo.getMethodName() + "\t"
		// + stackInfo.getClassName() + "\t"
		// + stackInfo.getShortClassName() + "("
		// + stackInfo.getFileName() + ":"
		// + stackInfo.getLineNum() + ")");
		// }
		// }
		// }
		System.out.println(ESTRepository.getDistinctAll().size());
	}

}
